package view;

import javax.imageio.ImageIO;
import javax.swing.*;

import controller.Poker;
import poker.Phase;
import poker.PlayerInfo;
import poker.WinInfo;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

public class PokerView extends JFrame implements Actionable {
	static final long serialVersionUID = 9996662;
	
	private CardLabel[] cardImgs;
	private JLabel[] playerNames;
	private JLabel[] playerBets;
	private JLabel[] playerTokens;
	
	private JLabel[] displayText;
	private JLabel[] displayInfo;
	
	private JComboBox<String> auctionAction;
	
	private JLabel displayMsg;
	
	private JPanel curPanel;
	private JPanel visionPanel;
	private JPanel auctionPanel;
	private JPanel exchangePanel;
	private JPanel endPanel;
	private JPanel botTurnPanel;
	
	private JPanel mainPanel;	
	private JPanel topPanel;
	private JPanel midPanel;
	private JPanel botPanel;
	
	private JPanel infoPanel;
	private JPanel commPanel;

	private JPanel resultsPanel;
	private JPanel resultsMidPanel;
	private JPanel[] playerResults;
	private JPanel[] playerResultCards;
	
	private JLabel[] playerResultText;
	private JLabel[][] resultCards;
	private JLabel resultLabel;
	
	private ChickenDialog chickDial;
	
	private InputButton chicken;
	private InputButton showCards;
	private InputButton exchangeEnter;
	private InputButton auctionEnter;
	private InputButton ender;
	private InputButton botEnter;
	private InputButton replay;
	
	private Phase phase;
	private Poker poker;
	private boolean[] cardData;
	private boolean botBool;
	private int[] cards;
	private int playerCount;
	private PokerViewWAdapt adapter;
	
	private PlayerInfo[] pInfoBank;
	private int[] cardsBank;
	private int curPlayerBank;
	private int poolBank;
	
	public PokerView(int playerCount) {
		super("Poker");
		this.playerCount = playerCount;
		cardImgs = new CardLabel[5];
		playerNames = new JLabel[playerCount];
		playerBets = new JLabel[playerCount];
		playerTokens = new JLabel[playerCount];
		displayText = new JLabel[3];
		displayInfo = new JLabel[3];
		displayMsg = new JLabel("message!", SwingConstants.CENTER);
		cardData = new boolean[5];
		botBool = false;
		
		String[] auctionStrings = new String[] { "Check", "Bet", "Call", "Raise", "Fold", "All-in" };
		auctionAction = new JComboBox<String>(auctionStrings);
		
		mainPanel = new JPanel();
		topPanel = new JPanel();
		midPanel = new JPanel();
		botPanel = new JPanel();
		
		infoPanel = new JPanel();
		commPanel = new JPanel();
		
		resultsPanel = new JPanel();
		resultsMidPanel = new JPanel();
		playerResults = new JPanel[playerCount];
		playerResultCards = new JPanel[playerCount];
		
		resultCards = new JLabel[playerCount][5];
		resultLabel = new JLabel();
		playerResultText = new JLabel[playerCount];
		
		visionPanel = new JPanel();
		auctionPanel = new JPanel();
		exchangePanel = new JPanel();
		endPanel = new JPanel();
		botTurnPanel = new JPanel();
		curPanel = new JPanel();
		
		chicken = new InputButton(this, "Odłącz gracza");
		showCards = new InputButton(this, "Pokaż karty");
		exchangeEnter = new InputButton(this, "Zatwierdź");
		auctionEnter = new InputButton(this, "Zatwierdź");
		ender = new InputButton(this, "Zakończ turę");
		botEnter = new InputButton(this, "Rozegraj turę bota");
		replay = new InputButton(this, "Jeszcze raz!");
		
		chickDial = new ChickenDialog(this, playerCount);
		
		mainPanel.setLayout(new BorderLayout());
		topPanel.setLayout(new GridLayout(3, playerCount));
		for(int i=0; i<playerCount; i++) {
			playerNames[i] = new JLabel("TestName", SwingConstants.CENTER);
			topPanel.add(playerNames[i]);
		}
		for(int i=0; i<playerCount; i++) {
			playerBets[i] = new JLabel("TestBet", SwingConstants.CENTER);
			topPanel.add(playerBets[i]);
		}
		for(int i=0; i<playerCount; i++) {
			playerTokens[i] = new JLabel("TestTokens", SwingConstants.CENTER);
			topPanel.add(playerTokens[i]);
		}
		midPanel.setLayout(new GridLayout(1, 5));
		BufferedImage pic;
		try {
			for(int i=0; i<5; i++) {
				pic = ImageIO.read(new File("img/0.png"));
				cardImgs[i] = new CardLabel(new ImageIcon(pic), this);
				midPanel.add(cardImgs[i]);
			}
		}
		catch(IOException e) {
			System.out.println("IOex");
			System.out.println(System.getProperty("user.dir"));
		}
		botPanel.setLayout(new BorderLayout());
		infoPanel.setLayout(new GridLayout(2, 3));
		displayText[0] = new JLabel("Pula", SwingConstants.CENTER);
		displayText[1] = new JLabel("Stawka", SwingConstants.CENTER);
		displayText[2] = new JLabel("Żetony", SwingConstants.CENTER);
		for(int i=0; i<3; i++) {
			infoPanel.add(displayText[i]);
		}
		for(int i=0; i<3; i++) {
			displayInfo[i] = new JLabel("0", SwingConstants.CENTER);
			infoPanel.add(displayInfo[i]);
		}
		botPanel.add(infoPanel, BorderLayout.LINE_START);
		commPanel.setLayout(new GridLayout(2, 1));
		commPanel.add(curPanel);
		commPanel.add(displayMsg);
		botPanel.add(commPanel, BorderLayout.CENTER);
		
		mainPanel.add(topPanel, BorderLayout.PAGE_START);
		//mainPanel.add(midPanel, BorderLayout.CENTER);
		mainPanel.add(botPanel, BorderLayout.PAGE_END);
		
		add(mainPanel);
		
		curPanel.add(visionPanel);
		
		visionPanel.add(showCards);
		
		auctionPanel.add(auctionAction);
		auctionPanel.add(auctionEnter);
		auctionPanel.add(chicken);
		
		exchangePanel.add(exchangeEnter);
		//exchangePanel.add(chicken);
		
		endPanel.add(ender);
		
		botTurnPanel.add(botEnter);
		
		resultsPanel.setLayout(new BorderLayout());
		resultsMidPanel.setLayout(new GridLayout(playerCount, 1));
		for(int i=0; i<playerCount; i++) {
			playerResults[i] = new JPanel();
			playerResults[i].setLayout(new BorderLayout());
			playerResultCards[i] = new JPanel();
			playerResultCards[i].setLayout(new GridLayout(1, 5));
			for(int j=0; j<5; j++) {
				resultCards[i][j] = new JLabel();
				resultCards[i][j].setHorizontalAlignment(SwingConstants.CENTER);
				playerResultCards[i].add(resultCards[i][j]);
			}
			playerResults[i].add(playerResultCards[i], BorderLayout.CENTER);
			playerResultText[i] = new JLabel();
			playerResults[i].add(playerResultText[i], BorderLayout.PAGE_END);
			resultsMidPanel.add(playerResults[i]);
		}
		resultsPanel.add(resultsMidPanel, BorderLayout.CENTER);
		resultsPanel.add(resultLabel, BorderLayout.PAGE_START);
		resultsPanel.add(replay, BorderLayout.PAGE_END);
		
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		setBounds(100, 100, 650, 500);
		setResizable(false);
		setVisible(true);
		adapter = new PokerViewWAdapt(chickDial);
		addWindowListener(adapter);
		
		phase = Phase.FirstAuction;
	}
	
	public void setController(Poker p) {
		poker = p;
	}
	
	@Override
	public void action(InputButton b) {
		if(b == auctionEnter) {
			if((String)auctionAction.getSelectedItem() != "Raise") {
				poker.auctionAction((String)auctionAction.getSelectedItem(), null);
			} else {
				String amount = (String)JOptionPane.showInputDialog
						(null, "Wprowadź stawkę:", "", JOptionPane.PLAIN_MESSAGE, null, null, null);
				poker.auctionAction((String)auctionAction.getSelectedItem(), amount);
			}
		} else if(b == botEnter) {
			poker.playBotTurn();
		} else if(b == exchangeEnter) {
			poker.exchangeAction(cardData);
		} else if(b == ender) {
			showData(pInfoBank, cardsBank, curPlayerBank, poolBank);
			hideCards();
		} else if(b == showCards) {
			curPanel.remove(visionPanel);
			if(phase == Phase.Exchange) {
				curPanel.add(exchangePanel);
			} else {
				curPanel.add(auctionPanel);
			}
			mainPanel.add(midPanel, BorderLayout.CENTER);
			mainPanel.revalidate();
			mainPanel.repaint();
		} else if(b == chicken) {
			chickDial.setVisible(true);
		} else if(b == replay) {
			poker.replay();
		}
		
	}
	
	@Override
	public void action(CardLabel cl) {
		if(phase != Phase.Exchange) return;
		int nr = 0;
		for(; nr<cardImgs.length; nr++) {
			if(cardImgs[nr] == cl) {
				break;
			}
		}
		BufferedImage img;
		if(cardData[nr]) {
			try {
				img = ImageIO.read(new File("img/" + cards[nr] + ".png"));
				cardImgs[nr].setIcon(new ImageIcon(img));
			} catch(IOException e) {
				System.out.println(e.getMessage());
			}
			cardData[nr] = false;
		} else {
			try {
				img = ImageIO.read(new File("img/" + cards[nr] + ".png"));
				BufferedImage overlay = ImageIO.read(new File("img/overlay.png"));
				Graphics g = img.getGraphics();
				g.drawImage(overlay, 0, 0, null);
				cardImgs[nr].setIcon(new ImageIcon(img));
			} catch(IOException e) {
				System.out.println(e.getMessage());
			}
			cardData[nr] = true;
		}
	}
	
	public void disconnect(int playerNumber) {
		poker.disconnect(playerNumber);
	}
	
	public void showMessage(String msg) {
		displayMsg.setText(msg);
	}
	
	public void setPhase(Phase p) {
		phase = p;
		if(phase == Phase.FirstAuction || phase == Phase.SecondAuction) {
			exchangePanel.remove(chicken);
			auctionPanel.add(chicken);
		} else if(phase == Phase.Exchange) {
			auctionPanel.remove(chicken);
			exchangePanel.add(chicken);
		} else if(phase == Phase.AnnounceWinner) {
			poker.requestResults();
		}
	}
	
	public void showData(PlayerInfo[] pInfo, int[] cards, int curPlayer, int pool) {
		botBool = false;
		for(int i=0; i<pInfo.length; i++) {
			if(i == curPlayer) {
				playerNames[i].setForeground(Color.RED);
				displayInfo[0].setText(Integer.toString(pool));
				displayInfo[1].setText(Integer.toString(pInfo[i].bet));
				displayInfo[2].setText(Integer.toString(pInfo[i].tokens));
			} else {
				playerNames[i].setForeground(Color.BLACK);
			}
			if(pInfo[i].isBot) { 
				playerNames[i].setText("(Bot) ");
			} else {
				playerNames[i].setText("");
			}
			playerNames[i].setText(playerNames[i].getText() + pInfo[i].name + " " + pInfo[i].status);
			playerBets[i].setText("Stawka: " + pInfo[i].bet);
			playerTokens[i].setText("Żetony: " + pInfo[i].tokens);
		}
		BufferedImage img;
		for(int i=0; i<cards.length; i++) {
			try {
				img = ImageIO.read(new File("img/" + cards[i] + ".png"));
				cardImgs[i].setIcon(new ImageIcon(img));
			} catch(IOException e) {
				System.out.println("IOex w showData");
			}
		}
		this.cards = cards;
		displayMsg.setText(Phase.stringify(phase) + ": " + "tura gracza nr " + (curPlayer+1));
		if(pInfo[curPlayer].isBot) {
			botBool = true;
			curPanel.removeAll();
			curPanel.add(botTurnPanel);
			mainPanel.validate();
			mainPanel.repaint();
		}
	}
	
	public void hideCards() {
		if(botBool) return;
		mainPanel.remove(midPanel);
		//mainPanel.add(fillerPanel, BorderLayout.CENTER);
		curPanel.removeAll();
		curPanel.add(visionPanel);
		mainPanel.validate();
		mainPanel.repaint();
	}
	
	public void redrawCards() {
		if(phase != Phase.Exchange) return;
		for(int i=0; i<5; i++) {
			BufferedImage img;
			if(!cardData[i]) {
				try {
					img = ImageIO.read(new File("img/" + cards[i] + ".png"));
					cardImgs[i].setIcon(new ImageIcon(img));
				} catch(IOException e) {
					System.out.println(e.getMessage());
				}
			} else {
				try {
					img = ImageIO.read(new File("img/" + cards[i] + ".png"));
					BufferedImage overlay = ImageIO.read(new File("img/overlay.png"));
					Graphics g = img.getGraphics();
					g.drawImage(overlay, 0, 0, null);
					cardImgs[i].setIcon(new ImageIcon(img));
				} catch(IOException e) {
					System.out.println(e.getMessage());
				}
			}
		}
	}
	
	public void receiveExchangerData(PlayerInfo[] pInfo, int[] cards, int curPlayer, int pool) {
		if(botBool) {
			showData(pInfo, cards, curPlayer, pool);
			hideCards();
		} else {
			pInfoBank = pInfo;
			cardsBank = cards;
			curPlayerBank = curPlayer;
			poolBank = pool;
			Arrays.fill(cardData, false);
			
			mainPanel.add(midPanel, BorderLayout.CENTER);
			curPanel.removeAll();
			curPanel.add(endPanel);
			displayMsg.setText("Wymieniłeś karty.");
			mainPanel.validate();
			mainPanel.repaint();
		}
	}
	
	public void showWinners(int[][] cards, WinInfo[] wInfo, String winString) {
		BufferedImage img;
		for(int i=0; i<cards.length; i++) {
			for(int j=0; j<5; j++) {
				try {
					img = ImageIO.read(new File("img/" + cards[i][j] + ".png"));
					resultCards[i][j].setIcon(new ImageIcon(img));
				} catch(IOException e) {
					System.out.println(e.getMessage());
				}
			}
			playerResultText[i].setText(wInfo[i].name + " " + wInfo[i].status + " - " + wInfo[i].hand + " | " + wInfo[i].tokens +
					" żetonów / wygranych: " + wInfo[i].winCount);
		}
		resultLabel.setText(winString);
		remove(mainPanel);
		add(resultsPanel);
		validate();
		repaint();
	}
	
	public void displayError(String e) {
		JOptionPane.showMessageDialog(null, e, "Error", JOptionPane.ERROR_MESSAGE);
	}
	
	public void prepareForNextGame(int playerCount) {
		if(playerCount != this.playerCount) {
			topPanel.removeAll();
			topPanel.setLayout(new GridLayout(3, playerCount));
			resultsMidPanel.removeAll();
			resultsMidPanel.setLayout(new GridLayout(playerCount, 1));
			for(int i=0; i<playerCount; i++) {
				topPanel.add(playerNames[i]);
			}
			for(int i=0; i<playerCount; i++) {
				topPanel.add(playerBets[i]);
			}
			for(int i=0; i<playerCount; i++) {
				topPanel.add(playerTokens[i]);
				resultsMidPanel.add(playerResults[i]);
			}
			chickDial = new ChickenDialog(this, playerCount);
			adapter.setDialog(chickDial);
		}
		
		remove(resultsPanel);
		add(mainPanel);
		validate();
		repaint();
	}
}
